package com.lagou.edu.factory;

import com.lagou.edu.annotation.MyAutowired;
import com.lagou.edu.annotation.MyService;
import com.lagou.edu.annotation.MyTransactional;
import com.mysql.cj.util.StringUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 应癫
 * <p>
 * 工厂类，生产对象（使用反射技术）
 */
public class BeanFactory {

    /**
     * 任务一：读取解析xml，通过反射技术实例化对象并且存储待用（map集合）
     * 任务二：对外提供获取实例对象的接口（根据id获取）
     */
    private static Map<String, Object> map = new HashMap<>();  // 存储对象

    private static final String BASE_PACKAGE = "src/main/java/com/lagou/edu";

    static {
        try {
            File file = new File(BASE_PACKAGE);
            setClassMap(file);
            dependency(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void setClassMap(File file) throws Exception {
        File[] fileList = file.listFiles();
        for (File file1 : fileList) {
            if (file1.isDirectory()) {
                setClassMap(file1);
            } else {
                String path = file1.getPath();
                String clazzString = path.substring(path.indexOf("com"), path.indexOf(".")).replaceAll("\\\\", ".");  // com.lagou.edu.annotation.Autowired.java
                Class<?> clazz = Class.forName(clazzString);
                boolean servicePresent = clazz.isAnnotationPresent(MyService.class);
                if (servicePresent) {
                    MyService service = clazz.getAnnotation(MyService.class);
                    String value = service.value();
                    if (StringUtils.isNullOrEmpty(value)) {
                        Class<?>[] interfaces = clazz.getInterfaces();
                        value = (interfaces != null && interfaces.length > 0) ?
                                firstCharacterToLower(interfaces[0].getSimpleName()) : firstCharacterToLower(clazz.getSimpleName());
                    }
                    Object instance = clazz.newInstance();
                    map.put(value, instance);
                }
            }
        }
    }

    private static void dependency(File file) throws Exception {
        //维护对象之间依赖关系
        for (Map.Entry<String, Object> entrySet : map.entrySet()) {
            Object obj = entrySet.getValue();
            Class clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(MyAutowired.class) && field.getAnnotation(MyAutowired.class).value()) {
                    String name = field.getName();
                    Method[] methods = clazz.getMethods();
                    for (Method method : methods) {
                        if (method.getName().equalsIgnoreCase("set" + name)) {
                            method.invoke(obj,map.get(name));
                        }
                    }
                }
            }

            if (clazz.isAnnotationPresent(MyTransactional.class)) {
                ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
                Class[] interfaces = clazz.getInterfaces();//获取类c实现的所有接口
                if (interfaces != null && interfaces.length > 0) {
                    obj = proxyFactory.getJdkProxy(obj);
                } else {
                    obj = proxyFactory.getCglibProxy(obj);
                }
            }
            map.put(entrySet.getKey(), obj);
        }
    }

    //  第一个字母转小写
    private static String firstCharacterToLower(String simpleName) {
        return Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
    }

    // 任务二：对外提供获取实例对象的接口（根据id获取）
    public static Object getBean(String id) {
        return map.get(id);
    }
}
